package com.timk.goserver.client.ui.screens;

import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.timk.goserver.client.model.Message;
import com.timk.goserver.client.services.MessageService;
import com.timk.goserver.client.services.NoSessionException;
import com.timk.goserver.client.ui.widgets.CenteredDialog;
import com.timk.goserver.client.ui.widgets.ChooseUserText;
import com.timk.goserver.client.ui.widgets.FocusCommand;
import com.timk.goserver.client.ui.widgets.NoFocusListener;
import com.timk.goserver.client.ui.widgets.StatusLabel;

/** Message dialog */
public class MessageDialog extends CenteredDialog {	// NOPMD - Complexity
	private final ChooseUserText toText;
	private final TextBox subjectText;
	private final TextArea messageText;
	final StatusLabel status;	// NOPMD - Explicit scoping
	private final Button sendButton;
	private final Button cancelButton;
	private final Button replyButton;
	private final Button closeButton;
	private final Button deleteButton;
	
	private final Message message;
	
	/**
	 * Creates a MessageDialog
	 * @param message the message
	 * @param newMessage true if sending a message
	 */
	public MessageDialog(Message message, // NOPMD - Complexity
			boolean newMessage) {
		super(null);
		
		this.message = message;
		
		if(newMessage) {
			setText("New Message");
		} else {
			setText(message.getSubject());
		}
		
		VerticalPanel mainPanel = new VerticalPanel();
		mainPanel.setSpacing(2);
		
		HorizontalPanel fromUserPanel = new HorizontalPanel();
		mainPanel.add(fromUserPanel);
		HTML fromLabel = new HTML("From:&nbsp;");
		fromUserPanel.add(fromLabel);
		TextBox fromText = new TextBox();
		fromUserPanel.add(fromText);
		fromUserPanel.setCellVerticalAlignment(fromLabel, 
				HasVerticalAlignment.ALIGN_MIDDLE);
		fromUserPanel.setWidth("100%");
		fromLabel.setWidth("100%");
		fromText.setWidth("100%");
		fromUserPanel.setCellWidth(fromLabel, "20%");
		fromUserPanel.setCellWidth(fromText, "80%");

		HorizontalPanel toUserPanel = new HorizontalPanel();
		mainPanel.add(toUserPanel);
		HTML toLabel = new HTML("To:&nbsp;");
		toUserPanel.add(toLabel);
		toText = new ChooseUserText();
		toUserPanel.add(toText);
		toUserPanel.setCellVerticalAlignment(toLabel, 
				HasVerticalAlignment.ALIGN_MIDDLE);
		toUserPanel.setWidth("100%");
		toLabel.setWidth("100%");
		toText.setWidth("100%");
		toUserPanel.setCellWidth(toLabel, "20%");
		toUserPanel.setCellWidth(toText, "80%");

		HorizontalPanel subjectPanel = new HorizontalPanel();
		mainPanel.add(subjectPanel);
		HTML subjectLabel = new HTML("Subject:&nbsp;");
		subjectPanel.add(subjectLabel);
		subjectText = new TextBox();
		subjectPanel.add(subjectText);
		subjectPanel.setCellVerticalAlignment(toLabel, 
				HasVerticalAlignment.ALIGN_MIDDLE);
		subjectPanel.setWidth("100%");
		subjectLabel.setWidth("100%");
		subjectText.setWidth("100%");
		subjectPanel.setCellWidth(subjectLabel, "20%");
		subjectPanel.setCellWidth(subjectText, "80%");
		
		Label commentLabel = new Label("Message:");
		mainPanel.add(commentLabel);
		messageText = new TextArea();
		mainPanel.add(messageText);
		messageText.setWidth("100%");
		mainPanel.setCellWidth(messageText, "300px");
		messageText.setHeight("100%");
		mainPanel.setCellHeight(messageText, "200px");
		
		status = new StatusLabel();
		mainPanel.add(status);
		
		HorizontalPanel buttonPanel = new HorizontalPanel();
		mainPanel.add(buttonPanel);
		mainPanel.setCellHorizontalAlignment(buttonPanel,
				HasHorizontalAlignment.ALIGN_CENTER);
		
		if(newMessage) {
			sendButton = new Button("Send");
			sendButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					onSend();
				}
			});
			sendButton.setWidth("60px");
			buttonPanel.add(sendButton);
			
			cancelButton = new Button("Cancel");
			cancelButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					hide();
				}
			});
			cancelButton.setWidth("60px");
			buttonPanel.add(cancelButton);
			
			replyButton = null;
			deleteButton = null;
			closeButton = null;
		}
		else {
			if("System".equals(message.getFromUser())) {
				replyButton = null;
			} else {
				replyButton = new Button("Reply");
				replyButton.addClickListener(new ClickListener() {
					public void onClick(Widget sender) {
						onReply();
					}
				});
				replyButton.setWidth("60px");
				buttonPanel.add(replyButton);
			}
			
			deleteButton = new Button("Delete");
			deleteButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					onDelete();
				}
			});
			deleteButton.setWidth("60px");
			buttonPanel.add(deleteButton);
			
			closeButton = new Button("Close");
			closeButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					hide();
				}
			});
			closeButton.setWidth("60px");
			buttonPanel.add(closeButton);
			
			messageText.addFocusListener(
					new NoFocusListener(messageText));
			
			sendButton = null;
			cancelButton = null;
		}
		
		setWidget(mainPanel);
		
		String fromUser = message.getFromUser();
		if(fromUser == null) {
			fromText.setText(MainPanel.loggedInUser.getUsername());
		} else {
			fromText.setText(fromUser);
		}
		fromText.setEnabled(false);

		FocusWidget focusWidget = toText.getTextBox();
		String toUser = message.getToUser();
		if(toUser != null) {
			toText.setUser(toUser);
			focusWidget = subjectText;
		}
		
		String subject = message.getSubject();
		if(subject != null) {
			subjectText.setText(subject);
			focusWidget = messageText;
		}
		
		String text = message.getText();
		if(text != null) {
			messageText.setText(text);
			focusWidget = null;
		}
		
		if(focusWidget != null) {
			DeferredCommand.add(new FocusCommand(focusWidget));
		}
	}
	
	void onSend() {
		String toUser = toText.getUser();
		if(toUser.length() < 1) {
			return;
		}
		
		String text = messageText.getText();
		if(text.length() < 1) {
			return;
		}
		
		Message msg = new Message();
		msg.setFromUser(MainPanel.loggedInUser.getUsername());
		msg.setToUser(toUser);
		msg.setSubject(subjectText.getText());
		msg.setText(text);
		
		enableButtons(false);
		MainPanel.msgService.sendMessage(msg, new AsyncCallback() {
			public void onSuccess(Object result) {
				enableButtons(true);
				
				int err = ((Integer)result).intValue();
				switch(err) {
				case MessageService.STATUS_SUCCESS:
					hide();
					break;
				case MessageService.STATUS_NO_SUCH_USER:
					status.setError("That user doesn't exist");
					break;
				default:
					status.setError("Unknown error: " + err);
					break;
				}
			}
			
			public void onFailure(Throwable caught) {
				if(caught instanceof NoSessionException) {
					MainPanel.sessionExpired(caught.getMessage());
					return;
				}
				
				enableButtons(true);
				status.setError("Error sending message: " + caught.getMessage());
			}
		});
	}
	
	void onDelete() {
		enableButtons(false);
		
		MainPanel.msgService.deleteMessage(message.getMessageId(), new AsyncCallback() {
			public void onSuccess(Object result) {
				enableButtons(true);
				int err = ((Integer)result).intValue();
				switch(err) {
				case MessageService.STATUS_SUCCESS:
					hide();
					break;
				case MessageService.STATUS_NO_SUCH_MESSAGE:
					status.setError("That message doesn't exist");
					break;
				default:
					status.setError("Unknown error: " + err);
					break;
				}
			}
			
			public void onFailure(Throwable caught) {
				if(caught instanceof NoSessionException) {
					MainPanel.sessionExpired(caught.getMessage());
					return;
				}
				
				enableButtons(true);
				status.setError("Error deleting message: " + caught.getMessage());
			}
		});
	}
	
	void onReply() {
		Message newMessage = new Message();
		newMessage.setToUser(message.getFromUser());
		newMessage.setFromUser(message.getToUser());
		if(message.getSubject().startsWith("Re:")) {
			newMessage.setSubject(message.getSubject());
		} else {
			newMessage.setSubject("Re: " + message.getSubject());
		}
		
		newMessage.setText(message.getFromUser() + " wrote:\n" + message.getText());
		
		MessageDialog dlg = new MessageDialog(newMessage, true);
		dlg.show();
	}
	
	void enableButtons(boolean enabled) {
		if(sendButton != null) {
			sendButton.setEnabled(enabled);
		}
		
		if(closeButton != null) {
			closeButton.setEnabled(enabled);
		}
		
		if(cancelButton != null) {
			cancelButton.setEnabled(enabled);
		}
		
		if(deleteButton != null) {
			deleteButton.setEnabled(enabled);
		}
		
		if(replyButton != null) {
			replyButton.setEnabled(enabled);
		}
	}
}
